package cc.ufinity.networkdiagnose.manager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import cc.ufinity.networkdiagnose.view.R;

import android.R.integer;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.WifiLock;
import android.os.Handler;

/**
 * 获取Wifi的AP，信号，RSSI等信息
 * 
 * @author ZR
 * 
 */
public final class WlanManager extends AbstractManager {

    public static final String SSID_CMCC_EDU = "CMCC-EDU";
    public static final String SSID_CMCC_AUTO = "CMCC-AUTO";
    public static final String SSID_CMCC = "CMCC";
    // 扫描热点超时
    public static final int SCAN_TIMEOUT = 50000;
    // 获得热点后，连接超时
    public static final int CONNECT_TIMEOUT = 30000;

    private WifiManager wifiManager;
    private WifiReceiver wifiReceiver;
    private DhcpReceiver dhcpReceiver;
    private PeapReceiver peapReceiver;
    private Peap2Receiver peapReceiver2;
    private WifiInfo wifiInfo;
    private int cdmaDbm;
    public Task task;
    public boolean filter;

    public List<APInfo> apInfo;

    public int getCdmaDbm() {
        return cdmaDbm;
    }

    public void setCdmaDbm(int cdmaDbm) {
        this.cdmaDbm = cdmaDbm;
    }

    private int evdoDbm;

    public int getEvdoDbm() {
        return evdoDbm;
    }

    public void setEvdoDbm(int evdoDbm) {
        this.evdoDbm = evdoDbm;
    }

    public List<Map<String, Object>> wifiList;

    private WifiLock wifiLock;

    private Activity context;

    public Activity getContext() {
        return context;
    }

    private boolean isScanTimout = false;

    private List<ScanResult> scanResults;
    private ScanResult currentScanResult;

    public ScanResult getCurrentScanResult() {
        return currentScanResult;
    }

    public void setCurrentScanResult(ScanResult currentScanResult) {
        this.currentScanResult = currentScanResult;
    }

    public List<ScanResult> getScanResults() {
        return scanResults;
    }

    public void setScanResults(List<ScanResult> scanResults) {
        this.scanResults = scanResults;
    }

    private Handler wifiReceiverHandler;

    private long startConntectTime;// 记录开始连接网络时间点

    public long getStartConntectTime() {
        return startConntectTime;
    }

    public void setStartConntectTime(long startConntectTime) {
        this.startConntectTime = startConntectTime;
    }
    private long startDisConntectTime;// 记录开始断开网络时间点 
    
    public long getStartDisConntectTime() {
		return startDisConntectTime;
	}

	public void setStartDisConntectTime(long startDisConntectTime) {
		this.startDisConntectTime = startDisConntectTime;
	}

	private long connectedConsumeTime;// 连接消耗时间

    private String ipAddress;

    private int current;
    private int currentNetworkId;

    public int getCurrentNetworkId() {
        return currentNetworkId;
    }

    public void setCurrentNetworkId(int currentNetworkId) {
        this.currentNetworkId = currentNetworkId;
    }

    public int getCurrent() {
        return current;
    }

    public void setCurrent(int current) {
        this.current = current;
    }

    public String getIpAddress() {
        return ipAddress;
    }

    public void setIpAddress(int ipAddress) {
        this.ipAddress = this.toIPAdress(ipAddress);
    }

    public long getConnectedConsumeTime() {
        return connectedConsumeTime;
    }

    public void setConnectedConsumeTime(long connectedConsumeTime) {
        this.connectedConsumeTime = connectedConsumeTime;
    }

    public Handler getWifiReceiverHandler() {
        return wifiReceiverHandler;
    }

    public boolean isScanTimout() {
        return isScanTimout;
    }

    public void setScanTimout(boolean isScanTimout) {
        this.isScanTimout = isScanTimout;
    }

    public WlanManager(Activity context) {
        this.context = context;
        wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    }

    public WifiInfo getWifiInfo() {
        return wifiInfo;
    }

    public void openWifi() {
        if (!wifiManager.isWifiEnabled()) {
            wifiManager.setWifiEnabled(true);
        }
    }

    public void closeWifi() {
        if (wifiManager.isWifiEnabled()) {
            wifiManager.setWifiEnabled(false);
        }
    }

    public void lockWifi() {
        wifiLock = wifiManager.createWifiLock("WLAN_LOCK");
        wifiLock.acquire();
    }

    public void unlockWifi() {
        if (wifiLock.isHeld()) {
            wifiLock.acquire();
        }
    }
    /**
     * 打开Wifi并扫描指定SSID网络
     */
    public void openAndScanAP(){
    	 openWifi();
    }
    public void startScan() {
        openWifi();
        wifiReceiver = new WifiReceiver(this, wifiManager);
        context.registerReceiver(wifiReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
        // 开始扫描热点
        wifiManager.startScan();
    }
    public void stopScan() {
        context.unregisterReceiver(wifiReceiver);
    }

    public List<Map<String, Object>> getWifiList() {
        return wifiList;
    }

    public void setWifiList(List<Map<String, Object>> result) {
        this.wifiList = result;
    }

    public String toIPAdress(final int i) {
        return (i & 0xFF) + "." + ((i >> 8) & 0xFF) + "." + ((i >> 16) & 0xFF) + "." + ((i >> 24) & 0xFF);
    }

    public WifiInfo getCurrentNetwork() {
        WifiInfo info = wifiManager.getConnectionInfo();
        return info;
    }
    
    // AP 关联测试，对CMCC,CMCC-EDU,CMCC-AUTO进行连接测试
    public void connect(final ScanResult scan) {
        wifiManager.disconnect();
        dhcpReceiver = new DhcpReceiver(this, wifiManager);
        context.registerReceiver(dhcpReceiver, new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION));
        setCurrentScanResult(scan);
        // WifiInfo info = wifiManager.getConnectionInfo();
        // if (info.getIpAddress() != 0) {
        	// wifiManager.disableNetwork(info.getNetworkId());
        // }
        this.setStartConntectTime(System.currentTimeMillis());
        List<WifiConfiguration> configs = wifiManager.getConfiguredNetworks();
        // if(info.getSSID().equals(ssid)){
        	// wifiManager.enableNetwork(info.getNetworkId(), true);
        // }
        enableNetwork(scan, configs);
    }
    public boolean isWifiEnabled() {
        return wifiManager.isWifiEnabled();
    }
    //对CMCC-AUTO进行连接测试
    public void connectPEAP(final ScanResult scan) {
    	if(wifiManager.isWifiEnabled())
    		wifiManager.disconnect();
    	peapReceiver = new PeapReceiver(this, wifiManager); 
        context.registerReceiver(peapReceiver, new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION));
        setCurrentScanResult(scan);
        this.setStartConntectTime(System.currentTimeMillis());
        List<WifiConfiguration> configs = wifiManager.getConfiguredNetworks();
        enableNetwork(scan, configs); 
     //   this.setStartDisConntectTime(System.currentTimeMillis());
	//	wifiManager.disconnect(); 
    }
    //对CMCC-AUTO进行断开连接测试
    public void disConnectPEAP(final ScanResult scan) {
    	peapReceiver2 = new Peap2Receiver(this, wifiManager); 
        context.registerReceiver(peapReceiver2, new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION));
        setCurrentScanResult(scan);
        this.setStartDisConntectTime(System.currentTimeMillis());
		wifiManager.disconnect(); 
    }
    
    //判断是否存在某SSID网络的配置信息
    public boolean isExistConfig(String SSID){ 
    	//连接网络
        List<WifiConfiguration> list = wifiManager.getConfiguredNetworks();
        if(list !=null){
        	 for (int i = 0; i < list.size(); i++) { 
             	WifiConfiguration wifiConfiguration = list.get(i); 
             	if(wifiConfiguration.SSID != null && wifiConfiguration.SSID.equals("\"" + SSID + "\"")) {
                 		return true;
                 }           
              }
        }
        return false;
    }
    
    //获取指定SSID网络的当前连接状态
    public int currentNetWorkStatus(String SSID){  
        List<WifiConfiguration> list = wifiManager.getConfiguredNetworks();
        if(list !=null){
        	 for (int i = 0; i < list.size(); i++) { 
             	WifiConfiguration wifiConfiguration = list.get(i); 
             	if(wifiConfiguration.SSID != null && wifiConfiguration.SSID.equals("\"" + SSID + "\"")) {
                 		return wifiConfiguration.status;
                 }           
              }
        }
        return WifiConfiguration.Status.DISABLED;
    }
    
    public void enableNetwork(ScanResult scan, List<WifiConfiguration> wifiConfiguration) {
        WifiConfiguration wcf = null;
        boolean exists = false;
        for (WifiConfiguration c : wifiConfiguration) {
            if (c.SSID.equals("\"" + scan.SSID + "\"")) {
                wcf = c;
                exists = true;
                break;
            }
        }

        if (null == wcf) {
            wcf = new WifiConfiguration();
            wcf.BSSID = scan.BSSID;
            wcf.SSID = "\"" + scan.SSID + "\"";

            wcf.hiddenSSID = false;
            wcf.status = WifiConfiguration.Status.ENABLED;
            wcf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
            wcf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
            wcf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
            wcf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
            wcf.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
            wcf.allowedProtocols.set(WifiConfiguration.Protocol.WPA);

            String mSecurity = scan.capabilities;
            // Log.e("secret", mSecurity);
            // 如果加密模式为WEP
            if (mSecurity.contains("WEP")) {
                wcf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
                wcf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
                wcf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
                // wcf.wepKeys[0] ="\"" + password + "\""; //This is the WEP
                // Password
                wcf.wepTxKeyIndex = 0;
            }
            // 如果加密模式为WPA EPA
            else if (mSecurity.contains("WPA-EAP")) {

            }
            // 如果加密模式为WPA PSK
            else if (mSecurity.contains("WPA-PSK")) {

            } else if (mSecurity.contains("WPA2-PSK")) {

            }
            // 无加密
            else {
                wcf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
            }
        }
        int id = exists ? wcf.networkId : wifiManager.addNetwork(wcf);
        wifiManager.enableNetwork(id, true);
    }
    
    public void registerRegDhcpRecevier(){
        
    }

    public void unRegDhcpRecevier() {
        context.unregisterReceiver(dhcpReceiver);
    }
    public void unRegReapRecevier() {
        context.unregisterReceiver(peapReceiver);
    }public void unRegReap2Recevier() {
        context.unregisterReceiver(peapReceiver2);
    }
    public void disConnect() {

        wifiManager.disconnect();
    } 
}

final class DhcpReceiver extends BroadcastReceiver {
    private WlanManager wlanManager;
    private WifiManager wifiManager;

    public DhcpReceiver(WlanManager wlanManager, WifiManager wifiManager) {
        this.wlanManager = wlanManager;
        this.wifiManager = wifiManager; 
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        // long start = System.currentTimeMillis();
        int ip = wifiManager.getConnectionInfo().getIpAddress();
        if (ip != 0) {
            wlanManager.setConnectedConsumeTime(System.currentTimeMillis());
            wlanManager.setIpAddress(ip);
            wlanManager.setCurrentNetworkId(wifiManager.getConnectionInfo().getNetworkId());
            wlanManager.unRegDhcpRecevier() ;
            wlanManager.sendMsg(MessageWhat.WIFI_SUCESS_CONNECTED);
        }      
    }

}

final class PeapReceiver extends BroadcastReceiver {
    private WlanManager wlanManager;
    private WifiManager wifiManager;
    public PeapReceiver(WlanManager wlanManager, WifiManager wifiManager) {
        this.wlanManager = wlanManager;
        this.wifiManager = wifiManager; 
    }

    @Override
    public void onReceive(Context context, Intent intent) {
    	 		// long start = System.currentTimeMillis();
         int ip = wifiManager.getConnectionInfo().getIpAddress();
         if (ip != 0) {
            wlanManager.setConnectedConsumeTime(System.currentTimeMillis());
            wlanManager.setIpAddress(ip);
            wlanManager.setCurrentNetworkId(wifiManager.getConnectionInfo().getNetworkId());
            wlanManager.unRegReapRecevier();
            wlanManager.sendMsg(MessageWhat.PEAP_SUCESS_CONNECTED);
         }      
    }

}
final class Peap2Receiver extends BroadcastReceiver {
    private WlanManager wlanManager;
    private WifiManager wifiManager;
    public Peap2Receiver(WlanManager wlanManager, WifiManager wifiManager) {
        this.wlanManager = wlanManager;
        this.wifiManager = wifiManager; 
    }

    @Override
    public void onReceive(Context context, Intent intent) {
         int ip = wifiManager.getConnectionInfo().getIpAddress();
         if (!(ip != 0)) {
            wlanManager.setConnectedConsumeTime(System.currentTimeMillis());
            wlanManager.setIpAddress(ip);
            wlanManager.setCurrentNetworkId(wifiManager.getConnectionInfo().getNetworkId());
            wlanManager.unRegReap2Recevier();
            wlanManager.sendMsg(MessageWhat.PEAP_SUCESS_DISCONNECTED);
         }      
    }

}
final class WifiReceiver extends BroadcastReceiver {
    private WlanManager wlanManager;
    private WifiManager wifiManager;

    public WifiReceiver(WlanManager wm, WifiManager wifiManager) {
        this.wlanManager = wm;
        this.wifiManager = wifiManager;
    }

    @Override
    public void onReceive(Context ctx, Intent intent) {
        List<ScanResult> scanResults = wifiManager.getScanResults();
        ComparatorLevel cl = new ComparatorLevel();
        Collections.sort(scanResults, cl);
        wlanManager.setScanResults(scanResults);
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        DBManager db = new DBManager((Activity) ctx);
        List<TaskConfig> tasks = db.getTask();
        db.release();
        for (ScanResult result : scanResults) {
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("ssid", result.SSID);
            map.put("mac", result.BSSID);
            map.put("level", result.level);
            map.put("snr", calcSNR(wlanManager.getCdmaDbm(), result.level));
            if (wlanManager.task != null) {
                if (db.taskFinished(tasks, result.BSSID, String.valueOf(wlanManager.task.id))) {
                    map.put("img", R.drawable.lock);
                    map.put("lock", "true");
                } else {
                    map.put("lock", "false");
                    if (result.level < -85) {
                        map.put("img", R.drawable.signal_low);
                    } else if (result.level > -75) {
                        map.put("img", R.drawable.signal_high);
                    } else {
                        map.put("img", R.drawable.signal_middle);
                    }
                }
            } else {
                map.put("lock", "false");
                if (result.level < -85) {
                    map.put("img", R.drawable.signal_low);
                } else if (result.level > -75) {
                    map.put("img", R.drawable.signal_high);
                } else {
                    map.put("img", R.drawable.signal_middle);
                }
            }
            map.put("scan", result);
            if (wlanManager.filter) {
                Iterator<APInfo> its = wlanManager.apInfo.iterator();
                APInfo info = null;
                while (its.hasNext()) {
                    info = its.next();
                    if (result.BSSID.equalsIgnoreCase(info.mac)) {
                        list.add(map);
                        break;
                    }
                }
            } else {
                list.add(map);
            }
        }
        wlanManager.setWifiList(list);
        wlanManager.sendMsg(MessageWhat.WIFI_RECEIVE_LIST);
    }

    public int calcSNR(int pl, int pn) {
        // double snr = Math.abs(pl) / pn;
        // snr = 10 * Math.log10(snr);
        int snr = pl - pn;
        return snr;

    }

    private final class ComparatorLevel implements Comparator<ScanResult> {

        @Override
        public int compare(ScanResult sr1, ScanResult sr2) {
            return String.valueOf(sr1.level).compareTo(String.valueOf(sr2.level));
        }

    }
}
